package gslog

import (
	"fmt"
	"runtime"
	"time"

	"github.com/fatih/color"
)

type consoleLog struct {
	logConfig *LogConfig
	logLevel  logLevel
}

func (x *consoleLog) Trace(msg string, fields ...any) {
	if x.logLevel > LEVEL_TRACE {
		return
	}

	data := msg
	if fields != nil {
		data = fmt.Sprintf(msg, fields...)
	}

	x.trace(data)
}

func (x *consoleLog) Debug(msg string, fields ...any) {
	if x.logLevel > LEVEL_DEBUG {
		return
	}

	data := msg
	if fields != nil {
		data = fmt.Sprintf(msg, fields...)
	}

	x.debug(data)
}

func (x *consoleLog) Info(msg string, fields ...any) {
	if x.logLevel > LEVEL_INFO {
		return
	}

	data := msg
	if fields != nil {
		data = fmt.Sprintf(msg, fields...)
	}

	x.info(data)
}

func (x *consoleLog) Warn(msg string, fields ...any) {
	if x.logLevel > LEVEL_WARN {
		return
	}

	data := msg
	if fields != nil {
		data = fmt.Sprintf(msg, fields...)
	}

	x.warn(data)
}

// 提取格式化错误信息的逻辑到单独的函数
func formatError(err ...any) string {
	if len(err) == 1 {
		if v, ok := err[0].(error); ok {
			return v.Error()
		}

		if v, ok := err[0].(string); ok {
			return v
		}

		return fmt.Sprintf("%v", err[0])
	}

	if v, ok := err[0].(string); ok {
		return fmt.Sprintf(v, err[1:]...)
	}

	return fmt.Sprintf("%v", err)
}

func (x *consoleLog) Error(err ...any) {
	// 可配置的调用栈深度
	const stackDepth = 20
	defer func() {
		pcs := make([]uintptr, stackDepth)
		callers := runtime.Callers(3, pcs)
		for i := 0; i < callers; i++ {
			f := runtime.FuncForPC(pcs[i])
			file, line := f.FileLine(pcs[i])
			fmt.Printf("%s\n\t%s:%d\n", f.Name(), file, line)
		}
	}()

	// 使用单独的函数格式化错误信息
	errorMsg := formatError(err...)
	x.error(errorMsg)
}

func (x *consoleLog) trace(data string) {
	fmt.Printf("[%s][TRACE] %s\n", x.now(x.logConfig.TimeFormat), data)
}

func (x *consoleLog) debug(data string) {
	fmt.Printf("[%s][DEBUG] %s\n", x.now(x.logConfig.TimeFormat), data)
}

func (x *consoleLog) info(data string) {
	fmt.Printf("[%s][INFO] %s\n", x.now(x.logConfig.TimeFormat), data)
}

func (x *consoleLog) warn(data string) {
	color.Yellow("[%s][WARN] %s\n", x.now(x.logConfig.TimeFormat), data)
}

func (x *consoleLog) error(data string) {
	color.Red("[%s][ERROR] %s\n", x.now(x.logConfig.TimeFormat), data)
}

func (x *consoleLog) GetLogLevel() logLevel {
	return x.logLevel
}

func (x *consoleLog) SetLogLevel(logLevel logLevel) {
	println("set loglevel: " + logLevel.String())
	x.logLevel = logLevel
}

// 根据指定模板返回当前时间。
func (x *consoleLog) now(layout string) string {
	if layout == "" {
		layout = "2006-01-02 15:04:05"
	}

	return time.Now().Format(layout)
}
